Skip to content

Prevent and optimize queries related to unindexed posts#23146

Open
leonidasmi wants to merge 4 commits intofeature/misc-performancefrom
21981-get_limited_unindexed_count-impacts-performance-alt
Open

Prevent and optimize queries related to unindexed posts#23146
leonidasmi wants to merge 4 commits intofeature/misc-performancefrom
21981-get_limited_unindexed_count-impacts-performance-alt

Conversation

@leonidasmi
Copy link
Copy Markdown
Contributor

@leonidasmi leonidasmi commented Apr 9, 2026

Context

Summary

This PR can be summarized in the following changelog entry:

  • Prevents unnecessary expensive DB queries when admin pages are being visited.
  • Optimizes expensive DB queries when performing actions related to the SEO optimization.

Relevant technical choices:

  • Makes the expensive get_total_unindexed() query to be run only once in sites where the SEOO never has run, at the time when we create the relevant notification, but not again.

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:

For preventing unnecessary queries:

  • In a fresh site, install Yoast SEO and Query monitor, dont run the SEO optimization and visit any admin page at least once before going into the next steps (this will make the query below run for the first time, which we can't avoid).
    • Instead of doing this in a fresh site, you can also do just enable the Enable media pages setting. That way, we make the site need another round of SEOO.
  • Delete all transients (wp transient delete --all) and go to any admin page

Without this PR:

  • You will see the Yoast\WP\SEO\Actions\Indexing\Abstract_Indexing_Action->get_total_unindexed query in the query list
  • Every time you delete transients and then visit an admin page, that query will be run

With this PR:

  • You will not see the Yoast\WP\SEO\Actions\Indexing\Abstract_Indexing_Action->get_total_unindexed query in the query list
  • Even if you delete transients and then visit an admin page, that query NOT will be run again.
  • Regression test:
    • You keep seeing in the topbar the notification counter indicating that you have a related notification to run the SEOO
    • You go to the Alert Center and you are able to see that notification

For optimizing queries:

  • Go to website with lots of posts, eg. the https://plugin-dev.yoastdemo.com/ one
  • Install a plugin that allows you to delete transients (eg. Transient manager) and Query Monitor
  • With this PR and without, go to Yoast->Dashboard and check in Query Monitor the time needed for the Yoast\WP\SEO\Actions\Indexing\Abstract_Indexing_Action->get_total_unindexed queries (the one about the posts should be more optimized)
    • Inbetween tests, delete the wpseo_total_unindexed_posts transient
  • Confirm that the time needed with this PR is less than without this PR

Regression tests:

  • For the get_count_query() change:
    • Add add_filter( 'Yoast\WP\SEO\enable_cron_indexing', '__return_false' ); to disable background indexation, to keep things from changing
    • In a site with not completed SEOO, run yoastIndexingData in the Yoast->Dashboard with this PR and without and confirm you get the same number. Make sure to delete all transients between refreshes.
    • In a site with complete SEOO, run yoastIndexingData in the Yoast->Dashboard with this PR and without and confirm you get 0 in both cases. Make sure to delete all transients between refreshes
  • For the get_select_query() change:
    • Complete the SEOO and go to any admin, non-Yoast page to confirm that you get the notification counter NOT indicating that you have that issue at the topbar. Going then to the Alert Center, you get the correct number of notifications, NOT including one that informs you to run the SEOO
    • Reset indexables, go to any admin, non-Yoast page to confirm that you get the notification counter indicating that you have that issue at the topbar. Going then to the Alert Center, you get the correct number of notifications, including one that informs you to run the SEOO.
  • Also, run the SEOO with this PR and without. Once it's finished, go to the indexable table and confirm that you get the same number of rows with each version.

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and commited the results, if my PR introduces new images or SVGs.

Innovation

  • No innovation project is applicable for this PR.
  • This PR falls under an innovation project. I have attached the innovation label.
  • I have added my hours to the WBSO document.

Fixes #

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 9, 2026

Coverage Report for CI Build 7

Coverage decreased (-0.6%) to 53.026%

Details

  • Coverage decreased (-0.6%) from the base build.
  • Patch coverage: 4 of 4 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 65341
Covered Lines: 34595
Line Coverage: 52.95%
Relevant Branches: 16414
Covered Branches: 8756
Branch Coverage: 53.34%
Branches in Coverage %: Yes
Coverage Strength: 46036.82 hits per line

💛 - Coveralls

@leonidasmi leonidasmi self-assigned this May 4, 2026
@leonidasmi leonidasmi modified the milestone: 27.7 May 5, 2026
@leonidasmi leonidasmi added the changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog label May 5, 2026
@leonidasmi leonidasmi marked this pull request as ready for review May 5, 2026 11:56
@leonidasmi leonidasmi changed the base branch from trunk to feature/misc-performance May 5, 2026 11:57
@leonidasmi leonidasmi added this to the feature/misc-performance milestone May 5, 2026
@leonidasmi leonidasmi removed their assignment May 5, 2026
@leonidasmi leonidasmi changed the title Use NOT EXISTS for post indexation action Prevent and optimize queries related to unindexed posts May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants